home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Games / flying-6.11 / xgraph.C < prev    next >
Encoding:
C/C++ Source or Header  |  1995-06-30  |  19.1 KB  |  812 lines

  1.  
  2. #if defined(SOLARIS)
  3. extern "C" int gettimeofday(struct timeval *tp);
  4. #endif
  5.  
  6. #if defined(SCO_ODT3)
  7. extern "C" int gettimeofday(struct timeval *tp, struct timezone *tzp);
  8. #endif
  9.  
  10. #include "pointer.h"
  11. #include "stipple.h"
  12. #ifndef _xsound_h
  13. #    include "xsound.h"
  14. #endif
  15.  
  16. #ifndef _game_h
  17. #    include "game.h"
  18. #endif
  19.  
  20. #include <stdarg.h>
  21.  
  22. Display    *dpy;
  23. Window    win, new_root;
  24. Colormap    cmap;
  25. int        scr;
  26.  
  27. static int        nbg_cols_all;
  28. static int        bg_unused;
  29. static int        nball_cols_to_alloc;
  30.  
  31. Pixmap    pointer_pmap;        // Pixmap (wird vom PBall benutzt)
  32. int        pointer_off_x, pointer_off_y;
  33.  
  34. static Pixmap        stipple_pmap=0;
  35. static const int    stipple_sz=128;
  36.  
  37. static unsigned long    start_seconds;
  38.  
  39. static int    info_ch = 0;
  40.  
  41. #ifdef STATISTICS
  42. static    GC    gc_text;
  43. static int    info_cw = 0;
  44.  
  45. static XFontStruct *fs = 0;
  46. static Font    info_font;
  47. static unsigned long info_fg, info_bg;
  48. static const int info_width = 16;
  49. static int info_offset = 0;
  50.  
  51. void showinfo( StatType stat, const char *info ) {
  52. static info_toggle=0;
  53.  
  54.     if (new_root) {
  55.         int len = strlen(info);
  56.         if (stat==OffsetInfo) {
  57.             if (len) {
  58.                 info_toggle^=1;
  59.                 if (info_toggle) {
  60.                     XSetForeground( dpy, gc_text, info_bg );
  61.                     XSetBackground( dpy, gc_text, info_fg );
  62.                 }
  63.             }
  64.             else {
  65.                 info = "                  ";
  66.                 len = 20;
  67.             }
  68.         }
  69.         XDrawImageString( dpy, new_root,
  70.             gc_text,
  71.             info_offset - (stat+1)*info_width*info_cw,
  72.             DisplayHeight(dpy,scr)- 1,
  73.             info, len);
  74.  
  75.         if ((stat==OffsetInfo) && (info_toggle)) {
  76.             XSetForeground( dpy, gc_text, info_fg );
  77.             XSetBackground( dpy, gc_text, info_bg );
  78.         }
  79.     }
  80. }
  81. #endif
  82.  
  83. static void InitTime() {
  84. struct timeval start;
  85.  
  86. #ifdef SOLARIS
  87.     gettimeofday( &start );
  88. #else
  89.     gettimeofday( &start, NULL );
  90. #endif
  91.     start_seconds = start.tv_sec;
  92. }
  93.  
  94. double GetCurrentTime() {
  95. struct timeval    current;
  96.  
  97. #ifdef SOLARIS
  98.     gettimeofday( ¤t );
  99. #else
  100.     gettimeofday( ¤t, NULL );
  101. #endif
  102.     return( ((double)(current.tv_sec-start_seconds))+(current.tv_usec/1000000.0) );
  103. }
  104.  
  105.  
  106. GC        gc_default;
  107.  
  108. GC        gc_lay1;
  109. GC        gc_lay2;
  110. GC        gc_cursor;
  111.  
  112. GC        gc_current;
  113.  
  114. GC        gc_bxor;
  115. GC        gc_bclear;
  116.  
  117. GC        gc_ballwhite;
  118. GC        gc_ball[MAX_BALL];
  119.  
  120.  
  121. void SetBgColor( ColorId col ) {
  122.     gc_current = gc_default;
  123.  
  124. //
  125. // set the foreground pixel
  126. //
  127.     if (col&BG_MASK) {
  128.         XSetForeground( dpy, gc_current, ball_pix[0]|bg_pix[col&COLOR_MASK] );
  129.     }
  130.     else if (col&STAT_MASK) {
  131.         XSetForeground( dpy, gc_current, stat_pix[col&COLOR_MASK] );
  132.     }
  133.     else {
  134.         XSetForeground( dpy, gc_current, ball_pix[col&COLOR_MASK] );
  135.     }
  136.  
  137. //
  138. // set background (when in mixed mode)
  139. //
  140.     if (col&MIX_MASK) {
  141.     //
  142.     // set background color
  143.     //
  144.         if ((col>>COLOR_BITS)&BG_MASK) {
  145.             XSetBackground( dpy, gc_current,
  146.                                 ball_pix[0]|bg_pix[(col>>COLOR_BITS)&COLOR_MASK] );
  147.         }
  148.         else if ((col>>COLOR_BITS)&STAT_MASK) {
  149.             XSetBackground(dpy,gc_current,stat_pix[(col>>COLOR_BITS)&COLOR_MASK]);
  150.         }
  151.         else {
  152.             XSetBackground(dpy,gc_current,ball_pix[(col>>COLOR_BITS)&COLOR_MASK]);
  153.         }
  154.  
  155.     //
  156.     // set (or create) background stipple
  157.     //
  158.         if (col&RAND_MASK) {
  159.         Pixmap rand_stipple_pmap=XCreatePixmap(dpy,win,stipple_sz,stipple_sz,1);
  160.             GC    gc = XCreateGC( dpy, rand_stipple_pmap, 0, 0l );
  161.             XSetFunction(dpy,gc,GXset);
  162.             XFillRectangle(dpy,rand_stipple_pmap,gc,0,0,stipple_sz,stipple_sz);
  163.             XSetFunction(dpy,gc,GXclear);
  164.             for (int i=stipple_sz*stipple_sz/
  165.                             ((int)((col&RAND_MASK)>>RAND_SHIFT)+1); i>0;i--) {
  166.                 XDrawPoint(dpy,rand_stipple_pmap,gc,rand()%stipple_sz,rand()%stipple_sz);
  167.             }
  168.             XFreeGC(dpy,gc);
  169.             XSetStipple( dpy, gc_current, rand_stipple_pmap );
  170.         }
  171.         else {
  172.             XSetStipple( dpy, gc_current, stipple_pmap );
  173.         }
  174.         XSetFillStyle( dpy, gc_current, FillOpaqueStippled );
  175.     }
  176.     else {
  177.         XSetFillStyle( dpy, gc_current, FillSolid );
  178.     }
  179. }
  180.  
  181. int StoreColor( unsigned pixel ) {
  182.             long    stat=-1;
  183. unsigned long    bgc;
  184.             int    nbgc;
  185. unsigned long    shc;
  186.             int    nshc;
  187. unsigned long    cuc;
  188. unsigned long    bc;
  189.             int    nbc;
  190.  
  191.         bgc = pixel&bg_mask;            // Hintergrund
  192.         for (nbgc=(nbg_cols_all-1)-1;nbgc>=0;nbgc--) {// passenden Index suchen
  193.             if (bg_pix[nbgc]==bgc)        break;
  194.         }
  195.         if ((bgc)&&nbgc>=nbg_cols) {
  196.                 stat = nbgc-nbg_cols;                // unbenutztes Pixel -> static
  197.         }
  198.  
  199.         shc = pixel&shade_mask;        // Schattierung
  200.         for (nshc=0;nshc<nshade_cols;nshc++) {            // passenden Index suchen
  201.             if (shade_pix[nshc]==shc)        break;
  202.         }
  203.         if ((shc)&&nshc>=nshade_cols) {
  204.                 printf( "not implemented: shaded %d free for static\n", pixel );
  205.                 return -1;        // unbenutztes Pixel
  206.         }
  207.  
  208.         cuc = pixel&cursor_mask;   // Cursor
  209.  
  210.         bc  = pixel-bgc-shc-cuc;    // Ballfarbe
  211.         for (nbc=0;nbc<nball_cols_to_alloc;nbc++) {        // passenden Index suchen
  212.             if (ball_pix[nbc]==bc)        break;
  213.         }
  214.         if (nbc>=nball_cols_to_alloc)        return -1;
  215.  
  216.         if (nbc>=nball_cols) {
  217.             stat = nball_cols*bg_unused + (nbc-nball_cols)*(nbg_cols_all)
  218.                     + ((nbgc>=0)?nbgc+1:0);
  219.         }
  220.         else {
  221.             if (stat>=0)    stat+=(nbc*bg_unused);
  222.         }
  223.  
  224. XColor     col;
  225.  
  226.     if (cuc&&(stat<nstat_cols)) {
  227.         XParseColor(dpy,cmap,cursor_col, &col );
  228.     }
  229.     else {
  230.         if (stat>=0) {
  231.             if (stat<nstat_cols) {
  232.                 XParseColor(dpy,cmap,stat_col[stat], &col );
  233.                 if (!shc) {
  234.                     DBG2( ShowColors, "Static %2ld at pixel %3d\n", stat, pixel );
  235.                     stat_pix[stat] = pixel;
  236.                 }
  237.             }
  238.             else return -1;
  239.         }
  240.         else if (nbc) {
  241.                 XParseColor(dpy,cmap,ball_col[nbc], &col );        // RGB-Werte lesen
  242.         }
  243.         else if (bgc) {
  244.                 XParseColor(dpy,cmap,bg_col[nbgc], &col );        // RGB-Werte lesen
  245.         }
  246.         else    XParseColor(dpy,cmap,ball_col[0], &col );
  247.  
  248.         if (shc) {
  249.             XColor    scol;
  250.             XParseColor(dpy,cmap,shade_col[nshc], &scol );    // RGB-Werte lesen
  251.  
  252.             col.red   = (col.red  *m[nshc] + scol.red  *d[nshc])/(m[nshc]+d[nshc]);
  253.             col.green = (col.green*m[nshc] + scol.green*d[nshc])/(m[nshc]+d[nshc]);
  254.             col.blue  = (col.blue *m[nshc] + scol.blue *d[nshc])/(m[nshc]+d[nshc]);
  255.         }
  256.     }
  257.  
  258.     col.pixel = pixel;
  259.     col.flags = DoRed|DoGreen|DoBlue;
  260.     XStoreColor( dpy,cmap,&col);
  261.     return 0;
  262. }
  263.  
  264. void StoreColors() {
  265.     for (int i=0;i<256;i++)    StoreColor(i);
  266. }
  267.  
  268.  
  269. void AllocColors() {
  270. unsigned long plane_mask[8];
  271. int    nplanes = 0;
  272. int    n;
  273.  
  274.     nball_cols_to_alloc = nball_cols;
  275. //
  276. // Ausrechnen, wieviele Planes ben÷tigt werden
  277. //
  278.     n = nbg_cols;        // Planes fⁿr Hintergrund sammeln
  279.     while( n )    { nplanes++;    n>>=1; }
  280.     nbg_cols_all = (1<<nplanes);
  281.     bg_unused    = nbg_cols_all-1-nbg_cols;
  282.     n = nshade_cols;
  283.     while( n )    { nplanes++;    n>>=1; }
  284.     if (cursor_col)    nplanes++;
  285.  
  286. //
  287. // Anfordern der Farben
  288. //
  289.     DBG1( ShowColors, "Graphic: %d planes\n", nplanes );
  290.     DBG1( ShowColors, "Graphic: %d ball colors\n", nball_cols );
  291.     DBG1( ShowColors, "Graphic: %d static colors\n", nstat_cols );
  292.     while (nstat_cols>nball_cols*bg_unused
  293.                             +(nball_cols_to_alloc-nball_cols)*(nbg_cols_all)) {
  294.         nball_cols_to_alloc++;
  295.     }
  296.     DBG1( ShowColors, "Graphic: %d statics 'between planes'\n", nball_cols*bg_unused );
  297.     DBG1( ShowColors, "Graphic: allocating %d ball colors\n", nball_cols_to_alloc );
  298.  
  299.     cmap = DefaultColormap( dpy, scr );
  300.     if (XAllocColorCells( dpy, cmap, False,
  301.                     plane_mask, nplanes, ball_pix, nball_cols_to_alloc )==0) {
  302.         DBG0( UnixTrace,
  303.                         "Allocation of colors failed - creating local colormap.\n" );
  304.         cmap= XCreateColormap(dpy,win,DefaultVisual(dpy,scr),AllocNone);
  305.         if (XAllocColorCells( dpy, cmap, False,
  306.                     plane_mask, nplanes, ball_pix, nball_cols_to_alloc )==0) {
  307.                 fprintf(stderr, "not enough colors: " );
  308.                 fprintf(stderr, "I need %d colors + %d planes.\n",
  309.                             nball_cols_to_alloc, nplanes );
  310.                 exit(0);
  311.         }
  312.         if (new_root) {
  313.                 XSetWindowAttributes    attrib;
  314.                 attrib.colormap = cmap;
  315.                 XChangeWindowAttributes( dpy, new_root, CWColormap, &attrib );
  316.         }
  317.         else    XSetWindowColormap( dpy, win, cmap );
  318.         XSync(dpy,0);
  319.     }
  320.  
  321. //
  322. // Verteilen der Planes auf die Farben
  323. //
  324. int c=0;
  325.     for (n=0;n<nbg_cols+bg_unused;n++) {
  326.         bg_pix[n] = 0;
  327.         if ((n+1)&1)        bg_pix[n]+=plane_mask[c+0];
  328.         if ((n+1)&2)        bg_pix[n]+=plane_mask[c+1];
  329.         if ((n+1)&4)        bg_pix[n]+=plane_mask[c+2];
  330.     }
  331.     n=nbg_cols;
  332.     bg_mask=0;
  333.     while(n)        { bg_mask+=plane_mask[c++];        n>>=1; }
  334.  
  335.     for (n=0;n<nshade_cols;n++) {
  336.         shade_pix[n] = 0;
  337.         if ((n+1)&1)        shade_pix[n]+=plane_mask[c+0];
  338.         if ((n+1)&2)        shade_pix[n]+=plane_mask[c+1];
  339.         if ((n+1)&4)        shade_pix[n]+=plane_mask[c+2];
  340.     }
  341.     n=nshade_cols;
  342.     shade_mask=0;
  343.     while(n)        { shade_mask+=plane_mask[c++];    n>>=1; }
  344.  
  345.     if (cursor_col) {
  346.         cursor_mask = plane_mask[c];
  347.     }
  348.  
  349.     ball_mask=0;
  350.     for (n=0;n<nball_cols_to_alloc;n++) {
  351.         ball_mask|=ball_pix[n];
  352.     }
  353. //
  354. // Farben eintragen
  355. //
  356.     StoreColors();                            // Farben in Tabelle eintragen
  357. //
  358. // GC's besetzen
  359. //
  360. unsigned long    value_mask;
  361. XGCValues        values;
  362.  
  363.     value_mask =    GCPlaneMask | GCForeground | GCBackground | GCFunction
  364.                     |    GCArcMode | GCStipple | GCFillStyle | GCGraphicsExposures;
  365.     values.graphics_exposures = False;
  366.     values.foreground = 0xffff;
  367.     values.background = 0;
  368.     values.function    = GXxor;
  369.     values.arc_mode    = ArcChord;        // statt ArcPieSlice
  370.     stipple_pmap      =
  371.     values.stipple        = XCreateBitmapFromData( dpy, RootWindow( dpy, scr ),
  372.                                     stipple_bits, stipple_width, stipple_height );
  373.     values.fill_style    = FillSolid;
  374. #ifdef STATISTICS
  375.     values.font= info_font;
  376.     if (values.font)    value_mask|=GCFont;
  377. #endif
  378.  
  379.     values.plane_mask  = bg_pix[0];
  380.     gc_lay1 = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
  381.     values.plane_mask  = shade_pix[0];
  382.     gc_lay2 = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
  383.  
  384.     values.plane_mask  = cursor_mask;
  385.     gc_cursor = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
  386.  
  387. //
  388. // Default Graphic-Context erzeugen
  389. //
  390.     values.foreground = ball_pix[0];
  391.     values.plane_mask = ball_mask | shade_pix[0];        // Arbeiten in lay2
  392.     values.function   = GXxor;
  393.     gc_bxor = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
  394.     values.function   = GXclear;
  395.     gc_bclear = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
  396.  
  397.     values.plane_mask    = ball_mask|shade_mask|bg_mask|cursor_mask;
  398.     values.function    = GXcopy;
  399.     gc_default = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
  400.  
  401.     values.plane_mask    = ball_mask;
  402.     gc_ball[0] = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
  403. //
  404. // Kontext fⁿr den Text
  405. //
  406. #ifdef STATISTICS
  407.     values.foreground = info_fg = ball_pix[0];
  408.     values.background = info_bg = GetAllocatedPixel( "black" );
  409.     values.plane_mask  = AllPlanes;
  410.     gc_text    = XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
  411.  
  412.     info_offset = (DisplayWidth(dpy,scr)+max_x)/2;
  413. #endif
  414. //
  415. // GC's fⁿr die Ballfarben
  416. //
  417. unsigned long white_pix=0;
  418.  
  419.     values.fill_style = FillSolid;
  420.     values.plane_mask = ball_mask;
  421.     values.function    = GXxor;
  422.     values.background = 0;
  423.     if (deluxe) {
  424.         white_pix = GetAllocatedPixel( "ivory" );
  425.         if (!white_pix) {
  426.             fprintf( stderr, "white color 'ivory' missing for ball-underground\n");
  427.             exit(-1);
  428.         }
  429.         values.foreground = (white_pix^ball_pix[0]);
  430.         gc_ballwhite=XCreateGC(dpy,RootWindow(dpy,scr),value_mask,&values);
  431.     }
  432.  
  433.  
  434.     for (int i=0;i<nball_ids;i++) {
  435.         ColorId    col = ball_ids[i];
  436.  
  437.         if (deluxe) values.foreground = white_pix^ball_pix[col&COLOR_MASK];
  438.         else            values.foreground = ball_pix[0]^ball_pix[col&COLOR_MASK];
  439.         if (col&MIX_MASK) {
  440.             values.foreground = ball_pix[0]^ball_pix[(col>>COLOR_BITS)&COLOR_MASK];
  441.             values.fill_style = FillOpaqueStippled;
  442.         }
  443.         else {
  444.             values.fill_style = FillSolid;
  445.         }
  446.  
  447.         gc_ball[i]=XCreateGC( dpy, RootWindow( dpy, scr ), value_mask, &values );
  448.     }
  449. //
  450. // Pixmaps erzeugen
  451. //
  452.     pointer_pmap = XCreatePixmapFromBitmapData(dpy,win,
  453.             pointer_bits, pointer_width, pointer_height, cursor_mask, 0,
  454.             DefaultDepth(dpy,scr) );
  455.     pointer_off_x = pointer_x_hot;
  456.     pointer_off_y = pointer_y_hot;
  457.  
  458. #ifdef DEBUG
  459.     if (debug&Sync) {
  460.         XSynchronize(dpy,1);
  461.     }
  462.     if ((debug&ShowSubWindow)&&(!new_root)) { 
  463.         XSizeHints                hints;
  464.  
  465.         hints.flags = USPosition | USSize | PAspect | PMinSize | PMaxSize;
  466.         hints.x = (DisplayWidth(dpy,scr) -max_x)/2;
  467.         hints.y = 0;
  468.         hints.width  = hints.min_width  = hints.max_width  = max_x;
  469.         hints.height = hints.min_height = hints.max_height = max_y;
  470.         XSetNormalHints( dpy,win,&hints );
  471.     }
  472. #endif
  473.  
  474.  
  475. #ifdef DEBUG
  476.     if (debug&ShowColors) {
  477. Window    help;
  478. const int lpixs_x = 16;
  479. const int lpixs_y = 16;
  480. const int d=16;
  481. const int o=2;
  482.  
  483.         help = CreateWindow("Farbtabelle",lpixs_x*(d+o)+1 ,lpixs_y*(d+o)+1);
  484.         for (int px=0;px<lpixs_x;px++) {
  485.             for (int py=0;py<lpixs_y;py++) {
  486.                 if (!StoreColor(px+py*lpixs_x)) {
  487.                     XSetForeground(dpy,gc_default,px+py*lpixs_x);
  488.                     XFillRectangle(dpy,help,gc_default,1+px*(d+o),1+py*(d+o),d,d );
  489.                 }
  490.             }
  491.         }
  492.     }
  493. #endif
  494. }
  495.  
  496.  
  497. void MapMainWindow() {
  498. XEvent    event;
  499.  
  500.     XSetWindowBackground( dpy, win, ball_pix[0] );
  501.     XMapRaised( dpy, win );
  502.     if (new_root) {
  503.         XSetWindowBackground( dpy, new_root, GetAllocatedPixel("black") );
  504.         XMapRaised( dpy, new_root );
  505.         XInstallColormap( dpy, cmap );
  506.     }
  507.     XWindowEvent( dpy, win, ExposureMask, &event );
  508.     XSetInputFocus( dpy, win, RevertToNone, CurrentTime );
  509. }
  510.  
  511.  
  512. Window CreateWindow( const char *name, int width, int height )
  513. {
  514. Window    win;
  515. XSetWindowAttributes    attrib;
  516. XSizeHints                hints;
  517. XEvent    event;
  518. static    int    offx=0;
  519. const    frame = 11;
  520.  
  521.     win = XCreateSimpleWindow( dpy, RootWindow(dpy,scr),
  522.                     0, 0, width, height,
  523.                     0, ball_pix[0], ball_pix[0] );
  524.     attrib.colormap = cmap;
  525.     XChangeWindowAttributes( dpy, win, CWColormap, &attrib );
  526.  
  527.     hints.flags = USPosition | USSize | PAspect | PMinSize | PMaxSize;
  528.     hints.x = DisplayWidth(dpy,scr) -offx-width-frame;
  529.     hints.y = DisplayHeight(dpy,scr)-height,
  530.     hints.width  = hints.min_width  = hints.max_width  = width;
  531.     hints.height = hints.min_height = hints.max_height = height;
  532.     XSetNormalHints( dpy,win,&hints );
  533.     offx+=width+2*frame;
  534.  
  535.     XStoreName( dpy, win, name );
  536.     XSelectInput( dpy,win,ExposureMask );
  537.     XMapRaised( dpy, win );
  538.     XWindowEvent( dpy, win, ExposureMask, &event );
  539.     return win;
  540. }
  541.  
  542. void InitGraphic( double x, double y )
  543. {
  544. XSetWindowAttributes    setwinattr;
  545.  
  546. #if (SOUND_SUBSYSTEM)
  547.     if (sound_request)        init_sound( "" );
  548. #endif
  549.  
  550.     dpy = XOpenDisplay( "" );
  551.     if (!dpy) {
  552.         fprintf( stderr, "can't open display\n" );
  553.         exit(0);
  554.     }
  555.     scr = DefaultScreen(dpy);
  556.  
  557. #ifdef STATISTICS
  558.     fs=XLoadQueryFont(dpy,"5x8");
  559.     if (!fs) {    fs=XLoadQueryFont(dpy,"6x10");
  560.                 if (!fs)    fs=XLoadQueryFont(dpy,"fixed");
  561.     }
  562.     if (fs) {
  563.         info_font = fs->fid;
  564.         info_cw   = XTextWidth(fs,"A",1);
  565.         info_ch   = fs->ascent + fs->descent;
  566.     }
  567. #endif
  568.  
  569. //
  570. // Gr÷▀e des Fensters bestimmen: Fenster zentrieren
  571. //
  572. int    dp_height = DisplayHeight(dpy,scr)-info_ch;
  573.  
  574.     world_x = x;
  575.     world_y = y;
  576.     if ( size>0 ) {
  577.         if (size>DisplayWidth(dpy,scr))        size = DisplayWidth(dpy,scr);
  578.         max_x = size;
  579.         max_y = (int)(size/world_x*world_y);
  580.         if (max_y>dp_height) {
  581.             max_y = dp_height;
  582.             size = max_x = (int)(max_y/world_y*world_x);
  583.         }
  584.     }
  585.     else if ( ((double)DisplayWidth(dpy,scr))/dp_height < world_x/world_y ) {
  586.         max_x  = DisplayWidth(dpy,scr);
  587.         max_y = (int)(max_x/world_x*world_y);
  588.     }
  589.     else {
  590.         max_y = dp_height;
  591.         max_x = (int)(max_y/world_y*world_x);
  592.     }
  593.  
  594. //
  595.     if ( size<=0 ) {
  596.         setwinattr.override_redirect = True;
  597.         new_root = XCreateSimpleWindow( dpy, RootWindow( dpy, scr ),
  598.                     0, 0, DisplayWidth( dpy,scr ), DisplayHeight( dpy,scr ),
  599.                     0, WhitePixel( dpy,scr ), BlackPixel( dpy,scr ) );
  600.         XChangeWindowAttributes( dpy, new_root, CWOverrideRedirect, &setwinattr );
  601.  
  602.         win = XCreateSimpleWindow( dpy, new_root,
  603.                     (DisplayWidth( dpy,scr )-max_x)/2,
  604.                     (dp_height-max_y)/2,
  605.                     max_x, max_y, 0, BlackPixel( dpy,scr ),WhitePixel( dpy,scr ) );
  606.         XSelectInput( dpy, new_root, KeyPressMask );
  607.         XSelectInput( dpy, win, ExposureMask|KeyPressMask );
  608.         setwinattr.backing_store = (0)?Always:NotUseful;
  609.         setwinattr.bit_gravity   = ForgetGravity;;
  610.         XChangeWindowAttributes(dpy,win,CWBitGravity|CWBackingStore,&setwinattr );
  611.         w2n = (max_x-2)/world_x;
  612.     }
  613.     else {
  614.         new_root = 0;
  615.         win = XCreateSimpleWindow( dpy, RootWindow( dpy, scr ),
  616.                     0,0 , max_x, max_y, 2, 0,0 );
  617.         XSelectInput( dpy, win, KeyPressMask|ExposureMask);
  618.         setwinattr.backing_store = (0)?Always:NotUseful;
  619.         setwinattr.bit_gravity   = ForgetGravity;;
  620.         XChangeWindowAttributes(dpy,win,CWBitGravity|CWBackingStore,&setwinattr );
  621.         w2n = (max_x-2)/world_x;
  622.     }
  623.  
  624. //
  625. // BellPitch einstellen
  626. //
  627.     InitTime();                    // Initialisierung der Zeitmessung
  628. }
  629.  
  630.  
  631. void CloseGraphic()
  632. {
  633. #ifdef STATISTICS
  634.     if (fs)        XFreeFont(dpy,fs);
  635. #endif
  636.     XFreePixmap( dpy, pointer_pmap );
  637.     XFreePixmap( dpy, stipple_pmap );
  638.  
  639.     XFreeGC( dpy, gc_default );
  640.  
  641.     XFreeGC( dpy, gc_lay1 );
  642.     XFreeGC( dpy, gc_lay2 );
  643.     XFreeGC( dpy, gc_cursor );
  644.  
  645.     XFreeGC( dpy, gc_bxor );
  646.     XFreeGC( dpy, gc_bclear );
  647.  
  648.     if (deluxe)        XFreeGC( dpy, gc_ballwhite );
  649.     for (int i=0;i<nball_ids;i++) {
  650.         XFreeGC( dpy, gc_ball[i] );
  651.     }
  652.  
  653. #ifdef STATISTICS
  654.     XFreeGC( dpy, gc_text );
  655. #endif
  656.  
  657.     if (new_root) {
  658.         XUninstallColormap( dpy, cmap );
  659.     }
  660.     if (cmap!=DefaultColormap( dpy, scr )) {
  661.         XFreeColormap(dpy,cmap);
  662.     }
  663.  
  664.     end_sound();
  665.     XSync( dpy, 0 );
  666.     XCloseDisplay( dpy );
  667. }
  668.  
  669.  
  670.  
  671.  
  672.  
  673. char    GetKey()
  674. {
  675. XEvent    event;
  676.  
  677.     XSync( dpy, 0 );
  678.     while (XEventsQueued( dpy, QueuedAfterFlush )) {
  679.         XNextEvent( dpy, &event );
  680.         switch( event.xany.type ) {
  681.         case KeyPress:
  682.         {    char                buffer;
  683.             XComposeStatus    compose;
  684.             KeySym            keysym;
  685.  
  686.             XLookupString( (XKeyEvent*)&event, &buffer, 1, &keysym, &compose );
  687.             if (isupper(buffer))        return tolower(buffer);
  688.             return buffer;
  689.         }
  690.         case Expose:
  691.         {
  692.             while( XCheckMaskEvent( dpy, ExposureMask, &event ));
  693.             XClearWindow( dpy, win );
  694.             g->ExposeRedraw();
  695.             PBallTop::ForAll( &PBallTop::Redraw );
  696.             break;
  697.         }
  698.         default:
  699.             break;
  700.         }
  701.     }
  702.     return 0;
  703. }
  704.  
  705.  
  706. #define XPix(x)    ((int)((x)*w2n))
  707. #define YPix(y)    ((int)((y)*w2n))
  708. #define Pix(r)        ((int)((r)*w2n))
  709.  
  710. void DrawLine( const Real& x1, const Real& y1, const Real& x2, const Real& y2 ) {
  711. int    px1 = XPix(x1);
  712. int    py1 = YPix(y1);
  713. int    px2 = XPix(x2);
  714. int    py2 = YPix(y2);
  715.     XDrawLine( dpy, win, gc_current, px1, py1, px2, py2 );
  716. }
  717.  
  718.  
  719. void DrawArc( const Real& x, const Real& y, const Real& r, const Real& from, const Real& angle ) {
  720. int    px  = XPix(x-r);
  721. int    py  = YPix(y-r);
  722. int    size= Pix(2.*r);
  723.  
  724.     XDrawArc( dpy, win, gc_current,
  725.                 px, py, size, size,
  726.                 (int)(from*64.), (int)(angle*64.) );
  727. }
  728.  
  729.  
  730. void DrawCircle( const Real& x, const Real& y, const Real& r ) {
  731. int    px  = XPix(x-r);
  732. int    py  = YPix(y-r);
  733. int    size= Pix(2.*r);
  734.  
  735.     XDrawArc( dpy, win, gc_current,
  736.                 px, py, size, size,
  737.                 0, (int)360*64 );
  738. }
  739.  
  740.  
  741. void FillArc( const Real& x, const Real& y, const Real& r, const Real& from, const Real& angle ) {
  742. int    px  = XPix(x-r);
  743. int    py  = YPix(y-r);
  744. int    size= Pix(2.*r);
  745.  
  746.     XFillArc( dpy, win, gc_current,
  747.                 px, py, size, size,
  748.                 (int)(from*64.), (int)(angle*64.) );
  749. }
  750.  
  751. void FillCircle( const Real& x, const Real& y, const Real& r ) {
  752. int    px  = XPix(x-r);
  753. int    py  = YPix(y-r);
  754. int    size= Pix(2.*r);
  755.  
  756.     XFillArc( dpy, win, gc_current,
  757.                 px, py, size, size,
  758.                 0, (int)360*64 );
  759. }
  760.  
  761.  
  762. void FillRectangle( const Real& x, const Real& y, const Real& width, const Real& height ) {
  763. int    px1 = XPix(x);
  764. int    py1 = YPix(y);
  765. int    px2 = XPix(x+width);
  766. int    py2 = YPix(y+height);
  767.     XFillRectangle( dpy, win, gc_current, px1, py1, px2-px1, py2-py1 );
  768. }
  769.  
  770. void FillPoly( int n, ... ) {
  771. va_list    argptr;
  772. Vec2    *v;
  773. int        i;
  774. XPoint    buffer[10];
  775. XPoint    *p;                // Zeiger auf Puffer, um gegebenenfalls mehr anzufordern
  776.  
  777.     va_start(argptr,n);
  778.  
  779.     if (sizeof(buffer)/sizeof(XPoint)<n)    p=new XPoint[n];
  780.     else                                                p=buffer;
  781.  
  782.     for (i=0;i<n;i++) {
  783.         v =  va_arg(argptr,Vec2*);
  784.         p[i].x = XPix(v->X());
  785.         p[i].y = YPix(v->Y());
  786.  
  787.     }
  788.     XFillPolygon( dpy,win,gc_current,p,n,0,0);
  789.  
  790.     if (p!=buffer)                                    delete p;
  791.     va_end(arg_ptr);
  792. }
  793.  
  794. void FillPoly( int n, Vec2 v[] ) {
  795. int        i;
  796. XPoint    buffer[10];
  797. XPoint    *p;
  798.  
  799.     if (sizeof(buffer)/sizeof(XPoint)<n)    p=new XPoint[n];
  800.     else                                                p=buffer;
  801.  
  802.     for (i=0;i<n;i++) {
  803.         p[i].x = XPix(v[i].X());
  804.         p[i].y = YPix(v[i].Y());
  805.     }
  806.     XFillPolygon( dpy,win,gc_current,p,n,0,0);
  807.  
  808.     if (p!=buffer)                                    delete p;
  809. }
  810.  
  811.  
  812.